package la.iok.hzsvn.lewin.movie.service;

import la.iok.hzsvn.lewin.movie.core.Token;
import la.iok.hzsvn.lewin.movie.core.exception.ErrorCode;
import la.iok.hzsvn.lewin.movie.entity.BookChapter;
import la.iok.hzsvn.lewin.movie.entity.PlayRole;
import la.iok.hzsvn.lewin.movie.entity.PlayRoleBook;
import la.iok.hzsvn.lewin.movie.mapper.PlayRoleBookMapper;
import la.iok.hzsvn.lewin.movie.model.PlayRoleBookVo;
import la.iok.hzsvn.lewin.mybatis.service.BaseServiceImpl;
import la.iok.hzsvn.share.annotations.NotNull;
import la.iok.hzsvn.share.annotations.NotNullElement;
import la.iok.hzsvn.share.annotations.Nullable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletResponse;
import java.util.Collections;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

@Service
public class PlayRoleBookServiceImpl extends BaseServiceImpl<PlayRoleBook, PlayRoleBookMapper,Long> implements PlayRoleBookService {
    private final MovieService movieService;
    private final PlayRoleService playRoleService;
    private final PlayRoleBookFileService playRoleBookFileService;
    private final BookChapterService bookChapterService;
    public PlayRoleBookServiceImpl(PlayRoleBookMapper mapper,
                                   MovieService movieService,
                                   PlayRoleService playRoleService,
                                   PlayRoleBookFileService playRoleBookFileService,
                                   BookChapterService bookChapterService) {
        super(mapper);
        this.movieService = movieService;
        this.playRoleService = playRoleService;
        this.playRoleBookFileService = playRoleBookFileService;
        this.bookChapterService = bookChapterService;
    }

    @org.jetbrains.annotations.NotNull
    private PlayRoleBook validate(Token token, Long id) {
        PlayRoleBook entity = select(id);
        ErrorCode.RECORD_NOT_EXIST.assertNotNull(entity,id);
        PlayRole role = playRoleService.select(entity.getPlayRoleId());
        ErrorCode.PROPERTY_CHECK_ERROR.assertNotNull(role,"角色","玩家角色不存在");
        movieService.validate(token,role.getMovieId());
        return entity;
    }

    @Transactional
    @Override
    public void delete(@NotNull Token token, @NotNull Long id){
        validate(token,id);
        delete(id);
    }

    @Transactional
    @Override
    public void deleteChapter(@NotNull Token token,@NotNull Long chapterId) {
        bookChapterService.delete(token,chapterId);
        List<PlayRoleBook> list = listByProperty("chapterId",chapterId);
        list.forEach(book->playRoleBookFileService.decrement(book.getFileId()));
        list.forEach(book->delete(book.getId()));
    }

    @Nullable
    private PlayRoleBook select(@Nullable Long playRoleId,@Nullable Long chapterId){
        if(playRoleId == null || chapterId == null){
            return null;
        }
        return mapper.select(playRoleId,chapterId);
    }

    @Override
    public Long uploadFile(@NotNull Token token, @NotNull Long playRoleId,@NotNull Long chapterId, @NotNull String path, @Nullable MultipartFile file) {
        path = ErrorCode.STORE_PATH_EMPTY_ERROR.assertNotBlank(path);
        PlayRole role = playRoleService.select(playRoleId);
        ErrorCode.PROPERTY_CHECK_ERROR.assertNotNull(role,"角色","玩家角色不存在");
        movieService.validate(token,role.getMovieId());
        BookChapter chapter = bookChapterService.select(chapterId);
        ErrorCode.PROPERTY_CHECK_ERROR.assertNotNull(chapter,"电子书章节","电子书章节不存在");
        PlayRoleBook entity = select(playRoleId,chapterId);
        if(entity == null){
            entity = new PlayRoleBook();
            entity.setChapterId(chapterId);
            entity.setPlayRoleId(playRoleId);
            insertSelective(entity);
        }
        Long fileId = playRoleBookFileService.uploadFile(file);
        playRoleBookFileService.decrement(entity.getFileId());
        update(entity.getId(),"fileId",fileId);
        update(entity.getId(),"filePath",path);
        playRoleBookFileService.increment(fileId);
        return entity.getId();
    }

    @Override
    public void downloadFile(Token token, HttpServletResponse response, Long id) {
        PlayRoleBook entity = validate(token,id);
        BookChapter chapter = bookChapterService.select(entity.getChapterId());
        ErrorCode.RECORD_NOT_EXIST.assertNotNull(chapter,entity.getChapterId());
        playRoleBookFileService.downloadFile(response,entity.getFileId(),chapter.getName());
    }

    @Nullable
    @Override
    public String digest(@Nullable Long id) {
        PlayRoleBook entity = select(id);
        if(entity == null){
            return null;
        }
        return playRoleBookFileService.digest(entity.getFileId());
    }

    @Nullable
    @Override
    public String storePath(@Nullable Long id) {
        PlayRoleBook entity = select(id);
        if(entity == null){
            return null;
        }
        return playRoleBookFileService.storePath(entity.getFileId());
    }

    @NotNull
    @NotNullElement
    @Override
    public List<PlayRoleBook> movieRoleBooks(@Nullable Long movieId) {
        if(movieId == null){
            return Collections.emptyList();
        }
        List<PlayRole> roles = playRoleService.list(movieId);
        Set<Long> roleIds = roles.stream().map(PlayRole::getId).collect(Collectors.toSet());
        if(roleIds.isEmpty()){
            return Collections.emptyList();
        }
        return listInProperty("playRoleId",roleIds,"playRoleId");
    }

    @NotNull
    @NotNullElement
    @Override
    public List<PlayRoleBookVo> movieRoleBooks(@NotNull Token token, @Nullable Long movieId) {
        if(movieId == null){
            return Collections.emptyList();
        }
        movieService.validate(token,movieId);
        return mapper.movieRoleBooks(movieId);
    }
}
